package com.aspire.boc.mms.gwcmp.action;

import java.io.IOException;
import java.math.BigDecimal;
import java.net.URLEncoder;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.lang.StringUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.poi.hssf.usermodel.HSSFCellStyle;
import org.apache.poi.hssf.usermodel.HSSFDataFormat;
import org.apache.poi.hssf.usermodel.HSSFRichTextString;
import org.apache.poi.hssf.usermodel.HSSFRow;
import org.apache.poi.hssf.usermodel.HSSFSheet;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.servlet.support.RequestContext;

import com.aspire.boc.mms.gwcmp.dao.GwcmpBillingMapper;
import com.aspire.boc.mms.gwcmp.model.GwcmpBilling;
import com.aspire.boc.mms.gwcmp.util.GwcmpAdminUtil;
import com.aspire.boc.mms.gwcmp.util.enums.BillingType;
import com.aspire.boc.mms.gwcmp.util.enums.SendMsgType;
import com.aspire.boc.mms.gwcmp.util.enums.ServiceType;
import com.aspire.boc.mms.wmf.util.Page;


/**
 * 计费管理
 * @author liming
 *
 */
@Controller
public class BillingAct {

	private static Log logger = LogFactory.getLog(BillingAct.class);
	
	@Autowired
	private GwcmpBillingMapper billingMapper;
	
	/**
	 * 新增/修改
	 * @param productId
	 * @param billingType
	 * @param cmccPrice
	 * @param unicomPrice
	 * @param telcomPrice
	 * @param billingOnSuccess
	 * @param request
	 * @param response
	 * @return
	 */
	@RequestMapping(value = "/billing/saveBilling.do")
	public @ResponseBody Map<String,Object> saveBilling(
			@RequestParam(value = "productId", required = false) String productId,
			@RequestParam(value = "billingType", required = false) Short billingType,
			@RequestParam(value = "cmccPrice", required = false) String cmccPrice,
			@RequestParam(value = "unicomPrice", required = false) String unicomPrice,
			@RequestParam(value = "telcomPrice", required = false) String telcomPrice,
			@RequestParam(value = "billingOnSuccess", required = false) Short billingOnSuccess,
			HttpServletRequest request, HttpServletResponse response){
		
		Map<String,Object> result = new HashMap<String, Object>();
		RequestContext requestContext = new RequestContext(request);
		//获取 操作人名称
		String operator = GwcmpAdminUtil.getLoginUserName(request);
		
		StringBuffer logInfo = new StringBuffer();
		logInfo.append("operator:").append(operator).append(",operation:/billing/saveBilling.do")
			.append(",params:[").append("productId=").append(productId).append(",billingType=").append(billingType)
			.append(",cmccPrice=").append(cmccPrice).append(",unicomPrice=").append(unicomPrice).append(",telcomPrice=").append(telcomPrice)
			.append(",billingOnSuccess=").append(billingOnSuccess).append("] ");
		logger.info(logInfo.toString());
		
		/**
		 * 参数验证
		 */
		if(StringUtils.isBlank(productId)){
			logger.error("operator:"+operator+",operation:/billing/saveBilling.do,[productId] is null");
			result.put("failure", Boolean.valueOf(true));
			result.put("msg",requestContext.getMessage("billing.error.billingId"));
			return result;
		}/*else if(productId.indexOf("PROD")!=0){
			logger.error("operator:"+operator+",operation:/billing/saveBilling.do,[productId] wrongful");
			result.put("failure", Boolean.valueOf(true));
			result.put("msg",requestContext.getMessage("billing.error.wrongful"));
			return result;
		}*/
		
		if(billingOnSuccess == null){
			billingOnSuccess = 0;
		}else if(billingOnSuccess != 1){
			billingOnSuccess = 0;
		}
		
		String regex = "[0-9]{1,10}(\\.[0-9]{1,2})?";
		if(cmccPrice!=null&&!regexCheck(regex,cmccPrice)){
			logger.error("operator:"+operator+",operation:/billing/saveBilling.do,errorMsg:[cmccPrice]:"+cmccPrice);
			result.put("failure", Boolean.valueOf(true));
			result.put("msg",requestContext.getMessage("billing.error.cmccPrice"));
			return result;
		}
		if(unicomPrice!=null&&!regexCheck(regex,unicomPrice)){
			logger.error("operator:"+operator+",operation:/billing/saveBilling.do,errorMsg:[unicomPrice]:"+unicomPrice);
			result.put("failure", Boolean.valueOf(true));
			result.put("msg",requestContext.getMessage("billing.error.unicomPrice"));
			return result;
		}
		if(telcomPrice!=null&&!regexCheck(regex,telcomPrice)){
			logger.error("operator:"+operator+",operation:/billing/saveBilling.do,errorMsg:[telcomPrice]:"+telcomPrice);
			result.put("failure", Boolean.valueOf(true));
			result.put("msg",requestContext.getMessage("billing.error.telcomPrice"));
			return result;
		}
		
		GwcmpBilling billing = new GwcmpBilling();
		billing.setBillingOnSuccess(billingOnSuccess);
		billing.setProductId(productId);
		billing.setBillingType(billingType);
		billing.setCmccPrice(cmccPrice==null?null:new BigDecimal(cmccPrice));
		billing.setUnicomPrice(unicomPrice==null?null:new BigDecimal(unicomPrice));
		billing.setTelcomPrice(telcomPrice==null?null:new BigDecimal(telcomPrice));
		billing.setLatestOperator(operator);
		billing.setLatestOperateTime(new Date());
		logger.info("operator:"+operator+",operation:/billing/saveBilling.do,param:"+billing);
		try {
			GwcmpBilling billingCheck = billingMapper.selectByPrimaryKey(productId);
			logger.info("operator:"+operator+",operation:/billing/saveBilling.do,method:selectByPrimaryKey("+productId+"),result:"+billingCheck);
			if(billingCheck==null){
				//新增
				billingMapper.insertSelective(billing);
			}else{
				//修改
				billingMapper.updateByPrimaryKeySelective(billing);
			}
			result.put("success", Boolean.valueOf(true));
		} catch (Exception e) {
			logger.error("operator:"+operator+",operation:/billing/saveBilling.do,errorMsg: ",e);
			result.put("failure", Boolean.valueOf(true));
			result.put("msg",requestContext.getMessage("common.error.systemError"));
			return result;
		}
		return result;
		
	}
	
	/**
	 * 详情
	 * @param productId
	 * @param request
	 * @param response
	 * @return
	 */
	@RequestMapping(value = "/billing/getBillingDetail.do")
	public @ResponseBody Map<String,Object> getBillingDetail(
			@RequestParam(value = "productId", required = true) String productId,
			HttpServletRequest request, HttpServletResponse response){
		
		Map<String,Object> result = new HashMap<String, Object>();
		RequestContext requestContext = new RequestContext(request);
		//获取 操作人名称
		String operator = GwcmpAdminUtil.getLoginUserName(request);
		
		StringBuffer logInfo = new StringBuffer();
		logInfo.append("operator:").append(operator).append(",operation:/billing/getBillingDetail.do")
			.append(",params:[").append("productId=").append(productId).append("] ");
		logger.info(logInfo.toString());
		
		/**
		 * 参数验证
		 */
		if(StringUtils.isBlank(productId)){
			logger.error("operator:"+operator+",operation:/billing/getBillingDetail.do,[productId] is null");
			result.put("failure", Boolean.valueOf(true));
			result.put("msg",requestContext.getMessage("billing.error.billingId"));
			return result;
		}/*else if(productId.indexOf("PROD")!=0){
			logger.error("operator:"+operator+",operation:/billing/getBillingDetail.do,[productId] wrongful");
			result.put("failure", Boolean.valueOf(true));
			result.put("msg",requestContext.getMessage("billing.error.wrongful"));
			return result;
		}*/
		
		GwcmpBilling billing = null;
		try {
			billing = billingMapper.selectBillingByProductId(productId);
			logger.info("operator:"+operator+",operation:/billing/getBillingDetail.do,method:selectBillingByProductId("+productId+"),result:"+billing);
		} catch (Exception e) {
			logger.error("operator:"+operator+",operation:/billing/getBillingDetail.do,errorMsg: ",e);
			result.put("failure", Boolean.valueOf(true));
			result.put("msg",requestContext.getMessage("common.error.systemError"));
			return result;
		}
		result.put("single", billing!=null?billing:new GwcmpBilling());
		return result;
		
	}
	
	/**
	 * 查询
	 * @param start
	 * @param limit
	 * @param productNameOrId
	 * @param ecNameOrId
	 * @param request
	 * @param response
	 * @return
	 */
	@RequestMapping(value = "/billing/getBillingList.do")
	public @ResponseBody Map<String,Object> getBillingList(
			@RequestParam(value = "start", required = true) int start,
            @RequestParam(value = "limit", required = true) int limit,
			@RequestParam(value = "productNameOrId", required = false) String productNameOrId,
			@RequestParam(value = "ecNameOrId", required = false) String ecNameOrId,
			HttpServletRequest request, HttpServletResponse response){
		
		Map<String,Object> result = new HashMap<String, Object>();
		RequestContext requestContext = new RequestContext(request);
		//获取 操作人名称
		String operator = GwcmpAdminUtil.getLoginUserName(request);
		
		StringBuffer logInfo = new StringBuffer();
		logInfo.append("operator:").append(operator).append(",operation:/billing/getBillingList.do")
			.append(",params: [").append("start=").append(start).append(",limit=").append(limit)
			.append(",productNameOrId=").append(productNameOrId).append(",ecNameOrId=").append(ecNameOrId).append("] ");
		logger.info(logInfo.toString());
		
		// 分页
		Map<String,Object> param = new HashMap<String, Object>();
		Page page = new Page(start, limit);
		param.put("page", page);
		param.put("orderByClause", "b.LATEST_OPERATE_TIME DESC");
		
		if(StringUtils.isNotBlank(productNameOrId)){
			param.put("productNameOrIdParam", "%"+StringUtils.trimToNull(productNameOrId)+"%");
		}
		if(StringUtils.isNotBlank(ecNameOrId)){
			param.put("ecNameOrIdParam", "%"+StringUtils.trimToNull(ecNameOrId)+"%");
		}
		logger.info("operator:"+operator+",operation: /billing/getBillingList.do,param:"+param);
		
		List<GwcmpBilling> list = null;
		Integer total = 0;
		try{
	        list = billingMapper.selectListByExample(param);
			total = billingMapper.totalByExample(param);
		} catch (Exception e) {
			logger.error("operator:"+operator+",operation:/billing/getBillingList.do,errorMsg: ",e);
			result.put("failure", Boolean.valueOf(true));
			result.put("msg",requestContext.getMessage("common.error.systemError"));
			return result;
		}
		result.put("total", total);
		result.put("list", list==null?new ArrayList<GwcmpBilling>(0):list);
        return result;
		
	}
	
	/**
	 * 导出
	 * @param productNameOrId
	 * @param ecNameOrId
	 * @param request
	 * @param response
	 */
	@RequestMapping(value = "/billing/exportBillingList.do")
	public void exportBillingList(
			@RequestParam(value = "productNameOrId", required = false) String productNameOrId,
			@RequestParam(value = "ecNameOrId", required = false) String ecNameOrId,
			HttpServletRequest request, HttpServletResponse response){
		
		//获取 操作人名称
		String operator = GwcmpAdminUtil.getLoginUserName(request);
		
		StringBuffer logInfo = new StringBuffer();
		logInfo.append("operator:").append(operator).append(",operation:/billing/exportBillingList.do")
			.append(",params:[").append("productNameOrId=").append(productNameOrId)
			.append(",ecNameOrId=").append(ecNameOrId).append("] ");
		logger.info(logInfo.toString());
		
		//参数
		Map<String,Object> param = new HashMap<String, Object>();
		param.put("orderByClause", "b.LATEST_OPERATE_TIME DESC");
		if(StringUtils.isNotBlank(productNameOrId)){
			param.put("productNameOrIdParam", "%"+StringUtils.trimToNull(productNameOrId)+"%");
		}
		if(StringUtils.isNotBlank(ecNameOrId)){
			param.put("ecNameOrIdParam", "%"+StringUtils.trimToNull(ecNameOrId)+"%");
		}
		logger.info("operator:"+operator+",operation:/billing/exportBillingList.do,param:"+param);
		
		List<GwcmpBilling> list = null;
		try{
	        list = billingMapper.selectListByExample(param);
		} catch (Exception e) {
			logger.error("operator:"+operator+",operation:/billing/exportBillingList.do,errorMsg:",e);
		}
		
		if(list == null) new ArrayList<GwcmpBilling>(0);
        HSSFWorkbook wb = writeBilling2Excel(list, response);
		String filename = "JFGL_"
				+ new SimpleDateFormat("yyyyMMdd").format(new Date())
				+ ".xls";
		downloadExcel(wb, filename, response);
	}
	
	// 创建工作量excel文件
  	private HSSFWorkbook writeBilling2Excel(
  			List<GwcmpBilling> list, HttpServletResponse response) {
  		
  		String[] titles = new String[]{"产品名称","产品ID","关联企业ID","关联企业名称","业务类型",
  				"服务种类","计费方式","移动价格","联通价格","电信价格","最后操作时间","操作账户"};
  		
  		/**
  		 * List<Map<String, Object>>
  		 */
  		HSSFWorkbook wb = new HSSFWorkbook();
  		HSSFCellStyle numStyle = wb.createCellStyle();
  		numStyle.setDataFormat(HSSFDataFormat.getBuiltinFormat("0"));
  		int size = list == null ? 0 : list.size();
  		if (size > 0) {
  			int sheetSize = 5000;
  			int sheetCount = (int) Math.ceil(size / sheetSize + 1);
  			
  			for (int n = 0; n < sheetCount; n++) {
  				HSSFSheet sheet = wb.createSheet("表" + (n + 1));
  				sheet.setDefaultColumnWidth((short) 10);
  				HSSFRow rowHead = sheet.createRow(0);

  				for(int i = 0;i<titles.length;i++){
	  				rowHead.createCell((short) i).setCellValue(
	  						new HSSFRichTextString(titles[i]));
  				}
  				// 10001: 0-4999, 5000-9999, 10000-10001
  				for (int j = n * sheetSize; j < list.size()
  						&& j < (n + 1) * sheetSize; j++) {
  					HSSFRow rowBody = sheet.createRow(j % sheetSize + 1);
  					GwcmpBilling billing = list.get(j);
  					rowBody.createCell((short) 0).setCellValue(
  							new HSSFRichTextString(billing.getProductName()));
  					rowBody.createCell((short) 1).setCellValue(
  							new HSSFRichTextString(billing.getProductId()));
  					rowBody.createCell((short) 2).setCellValue(
  							new HSSFRichTextString(billing.getEcId()));
  					rowBody.createCell((short) 3).setCellValue(
  							new HSSFRichTextString(billing.getEcName()));
  					//业务类型
  					SendMsgType sendMsgType = SendMsgType.getResStringByKey(getNullString(billing.getBusinessType()));
  					String entry = sendMsgType==null?"":sendMsgType.getStrValue();
  					rowBody.createCell((short) 4).setCellValue(
	  						new HSSFRichTextString(entry));
  					//服务种类
  					ServiceType serviceType = ServiceType.getResStringByKey(getNullString(billing.getServiceType()));
  					entry = serviceType==null?"":serviceType.getStrValue();
  					rowBody.createCell((short) 5).setCellValue(
  							new HSSFRichTextString(entry));
  					//计费类型
  					BillingType billingType = BillingType.getResStringByKey(getNullString(billing.getBillingType()));
  					entry = billingType==null?"":billingType.getStrValue();
  					rowBody.createCell((short) 6).setCellValue(
  							new HSSFRichTextString(entry));
  					rowBody.createCell((short) 7).setCellValue(
  							new HSSFRichTextString(getNullString(billing.getCmccPrice())));
  					rowBody.createCell((short) 8).setCellValue(
  							new HSSFRichTextString(getNullString(billing.getUnicomPrice())));
  					rowBody.createCell((short) 9).setCellValue(
  							new HSSFRichTextString(getNullString(billing.getTelcomPrice())));
  					Date operateTime = billing.getLatestOperateTime();
  					if(operateTime!=null){
  						SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
  						entry = format.format(operateTime);
  					}
  					rowBody.createCell((short) 10).setCellValue(
  							new HSSFRichTextString(entry));
  					rowBody.createCell((short) 11).setCellValue(
  							new HSSFRichTextString(getNullString(billing.getLatestOperator())));
  				}
  			}
  		}
  		return wb;
  	}
	
	/**
	 * @param wb
	 * @param filename
	 * @param response
	 */
	private void downloadExcel(HSSFWorkbook wb, String filename,
			HttpServletResponse response) {

		ServletOutputStream out = null;
		try {
			out = response.getOutputStream();
			response.setHeader("Content-Type", "application/force-download");
			response.setHeader("Content-Disposition", "attachment;filename="
					+ URLEncoder.encode(filename, "UTF-8"));
			wb.write(out);
			out.close();
		} catch (Exception e) {
			logger.error(">>>>>fail to write output stream", e);
		} finally {
			if (out != null) {
				try {
					out.close();
				} catch (IOException e) {
					logger.error(">>>>>fail to close output stream", e);
				}
			}
		}
	}
	
	private String getNullString(Object data){
		if(data == null){
			return "";
		}
		String dataStr = String.valueOf(data);
		if("null".equalsIgnoreCase(dataStr)){
			return "";
		}
		return dataStr;
	}
	
	/**
	 * 正则校验
	 * @param regex 正则规则
	 * @param msg	校验内容
	 * @return
	 */
	private boolean regexCheck(String regex,String msg){
		if(msg==null||regex==null){
			return false;
		}
		Pattern pattern = Pattern.compile(regex);  
		Matcher matcher = pattern.matcher(msg); 
		return matcher.matches();
	}
}
